/*
 * DatabaseManager.cpp
 *
 *  Created on: 22/09/2011
 *      Author: Arthur Holanda
 *      Author: Demontie Junior
 */

#include "db/DatabaseManager.h"
#include "db/InfoDB.h"

DatabaseManager::DatabaseManager() {
}

void DatabaseManager::Construct() {
	result r;

	String dbLocation("/Home/Profile");

	if (database.Exists(dbLocation)) {

		r = database.Construct(dbLocation, false);

		if (IsFailed(r)) {
			AppLog("Falhou ao carregar o banco de dados.");
		} else {
			AppLog("Construiu baseado em anterior.");
		}

	} else {
		r = database.Construct(dbLocation, true);
		if (IsFailed(r)) {
			AppLog("Falhou ao construir ranking.");
		} else {
			String
					statement(
							"CREATE TABLE IF NOT EXISTS Profile(nome TEXT, cofre INTEGER)");

			r = database.ExecuteSql(statement, true);
			if (IsFailed(r)) {
				AppLog("Falhou ai construir tabela dos perfis");
			} else {
				AppLog("Construiu nova tabela com sucesso");
			}
		}
	}
}

DatabaseManager::~DatabaseManager() {
}

InfoDB *DatabaseManager::GetInfoPorPosicao(int posicao) {
	DbStatement* pStatement;
	DbEnumerator* pEnum;
	String statement;
	result r = E_SUCCESS;

	String nome;
	int cofre;
	InfoDB* info = new InfoDB();

	statement = (L"SELECT * FROM Profile ORDER BY cofre DESC");

	pStatement = database.CreateStatementN(statement);

	if(!pStatement) goto CATCH;

	pEnum = database.ExecuteStatementN(*pStatement);
	if(!pEnum) goto CATCH;

	r = pEnum->Reset();

	for (int i = 0; i < posicao; ++i) {
		r = pEnum->MoveNext();
	}

	r = pEnum->GetStringAt(0, nome);
	r = pEnum->GetIntAt(1, cofre);

	if(IsFailed(r))
	return info;

	info->Construct(nome, cofre);

	delete pStatement;
	delete pEnum;

	return info;

	CATCH:
	result res = GetLastResult();

	if(res == E_SUCCESS) {

	} else if(res == E_INVALID_STATE) {

	} else if(res == E_INVALID_ARG ) {

	} else if(res == E_DATABASE) {

	} else if(res == E_SERVICE_BUSY) {

	} else {

	}

	if(pEnum) delete pEnum;
	if(pStatement) delete pStatement;

	return info;
}

void DatabaseManager::Inserir(InfoDB *info) {
	result r = E_SUCCESS;

	DbStatement* pStatement;
	String statement;

	r = database.BeginTransaction();

	if (IsFailed(r)) {
		AppLog("Falhou ao iniciar inserir.");
		return;
	}

	statement = "INSERT INTO Profile(nome, cofre) VALUES (?, ?)";

	pStatement = database.CreateStatementN(statement);
	if (IsFailed(r)) {
		AppLog("Falhou ao criar statement.");
		return;
	}

	r = pStatement->BindString(0, info->GetNome());
	if (IsFailed(r))
		goto CATCH;

	r = pStatement->BindInt(1, info->GetCofre());
	if (IsFailed(r))
		goto CATCH;

	database.ExecuteStatementN(*pStatement);
	r = database.CommitTransaction();

	AppLog("Inseriu");

	delete pStatement;
	return;

	CATCH: if (pStatement)
		delete pStatement;
	return;
}

void DatabaseManager::Limpar() {
	result r = E_SUCCESS;

	DbStatement* pStatement;
	String statement;

	r = database.BeginTransaction();

	if (IsFailed(r)) {
		AppLog("Falhou ao iniciar inserir.");
		return;
	}

	statement = "DELETE FROM Profile";

	pStatement = database.CreateStatementN(statement);
	if (IsFailed(r)) {
		AppLog("Falhou ao criar statement.");
		return;
	}

	database.ExecuteStatementN(*pStatement);
	r = database.CommitTransaction();

	delete pStatement;

	return;
}

InfoDB *DatabaseManager::GetInfoPorNome(String paramNome)
{
	DbStatement* pStatement;
	DbEnumerator* pEnum;
	String statement;
	result r = E_SUCCESS;

	String nome;
	int cofre;
	InfoDB* info = new InfoDB();

	statement = (L"SELECT * FROM Profile WHERE name = ?");

	pStatement = database.CreateStatementN(statement);

	if(!pStatement) goto CATCH;

	r = pStatement->BindString(0, paramNome);
	if (IsFailed(r))
		goto CATCH;

	pEnum = database.ExecuteStatementN(*pStatement);
	if(!pEnum) goto CATCH;

	r = pEnum->Reset();

	r = pEnum->MoveNext();

	r = pEnum->GetStringAt(0, nome);
	r = pEnum->GetIntAt(1, cofre);

	if(IsFailed(r))
	return info;

	info->Construct(nome, cofre);

	delete pStatement;
	delete pEnum;

	return info;

	CATCH:
	result res = GetLastResult();

	if(res == E_SUCCESS) {

	} else if(res == E_INVALID_STATE) {

	} else if(res == E_INVALID_ARG ) {

	} else if(res == E_DATABASE) {

	} else if(res == E_SERVICE_BUSY) {

	} else {

	}

	if(pEnum) delete pEnum;
	if(pStatement) delete pStatement;

	return info;
}

void DatabaseManager::Atualizar(InfoDB* info) {
	result r = E_SUCCESS;

	DbStatement* pStatement;
	String statement;

	r = database.BeginTransaction();

	if (IsFailed(r)) {
		AppLog("Falhou ao iniciar inserir.");
		return;
	}

	statement = "UPDATE Profile SET cofre = ? WHERE nome = ?";

	pStatement = database.CreateStatementN(statement);
	if (IsFailed(r)) {
		AppLog("Falhou ao criar statement.");
		return;
	}

	r = pStatement->BindInt(0, info->GetCofre());
	if (IsFailed(r))
		goto CATCH;

	r = pStatement->BindString(1, info->GetNome());
	if (IsFailed(r))
		goto CATCH;

	database.ExecuteStatementN(*pStatement);
	r = database.CommitTransaction();

	delete pStatement;
	return;

	CATCH: if (pStatement)
		delete pStatement;
	return;
}

ArrayList *DatabaseManager::GetPerfisOrderByNome()
{
	return GetPerfis("SELECT * FROM Profile");
}

ArrayList *DatabaseManager::GetPerfisOrderByCofre()
{
	return GetPerfis("SELECT * FROM Profile ORDER BY cofre DESC");
}

ArrayList* DatabaseManager::GetPerfis(String statement) {
	DbStatement* pStatement;
	DbEnumerator* pEnum;
	//		String statement;
	ArrayList* list = new ArrayList();
	list->Construct();
	result r = E_SUCCESS;

	String nome;
	int cofre;

	//		statement = (L"SELECT * FROM Profile ORDER BY cofre DESC");

	pStatement = database.CreateStatementN(statement);
	AppLog("Statement criado");

	if (!pStatement)
		goto CATCH;

	pEnum = database.ExecuteStatementN(*pStatement);
	AppLog("Statement executado");
	if (!pEnum)
		goto CATCH;

	r = pEnum->Reset();

	int columns;
	columns = pEnum->GetColumnCount();
	int numResultados;
	numResultados = 0;

	while (true) {
		InfoDB* info = new InfoDB();

		r = pEnum->MoveNext();

		if (IsFailed(r))
			goto CATCH;

		numResultados++;
		r = pEnum->GetStringAt(0, nome);
		r = pEnum->GetIntAt(1, cofre);

		if (IsFailed(r))
			return list;

		info->Construct(nome, cofre);

		list->Add(*info);
	}
	delete pStatement;
	delete pEnum;

	return list;

	CATCH: result res = GetLastResult();

	if (res == E_SUCCESS) {
		AppLog("%d resultados", numResultados);
		return list;
	} else if (res == E_OUT_OF_RANGE ) {
		return list;
	} else if (res == E_INVALID_STATE) {
		AppLog("E_INVALID_STATE");
	} else if (res == E_INVALID_ARG) {
		AppLog("E_INVALID_ARG");
	} else if (res == E_DATABASE) {
		AppLog("E_DATABASE");
	} else if (res == E_SERVICE_BUSY) {
		AppLog("E_SERVICE_BUSY");
	} else {
		AppLog("else");
	}

	if (pEnum)
		delete pEnum;
	if (pStatement)
		delete pStatement;

	return list;
}

void DatabaseManager::Remove(String nome)
{
	result r = E_SUCCESS;

		DbStatement* pStatement;
		String statement;

		r = database.BeginTransaction();

		if (IsFailed(r)) {
			AppLog("Falhou ao iniciar inserir.");
			return;
		}

		statement = "DELETE FROM Profile WHERE nome = ?";

		pStatement = database.CreateStatementN(statement);
		if (IsFailed(r)) {
			AppLog("Falhou ao criar statement.");
			return;
		}

		r = pStatement->BindString(0, nome);
		if (IsFailed(r))
			goto CATCH;

		database.ExecuteStatementN(*pStatement);
		r = database.CommitTransaction();

		delete pStatement;

		return;

		CATCH: if (pStatement)
				delete pStatement;
		return;
}


